package edu.gmu.dglidde2.ece612.scheduler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Unit test suite for the successful creation of {@link Task} objects with
 * valid parameters.
 * 
 * @see RunWith
 * @see Parameterized
 * @author Doug Glidden
 */
@RunWith(Parameterized.class)
public class CreateTask {

	// Each row of this array provides a set of input parameters passed to the
	// test's constructor.
	protected static Object[][] DATA = new Object[][] {
			{ "P0", 1, 1, 1, 1, new String[] { "A", "B", "C" } },
			{ "task-0", 0, 1, 2, 3, new String[] { "N0", "N1" } },
			{ "JOB 1", 1, 2, 3, 4, new String[] { "processor-0" } },
			{ "A", 10, 10, 10, 10, new String[] { "PROCESSOR 1" } } };

	private Task task;

	private String name;
	private long phase;
	private long period;
	private long executionTime;
	private long relativeDeadline;
	private Set<String> processorNames;

	/**
	 * Provides parameters to be injected into the test class constructor.
	 * 
	 * @see Parameterized
	 * @return the test parameters.
	 */
	@Parameters
	public static Collection<Object[]> getData() {
		return Arrays.asList(DATA);
	}

	/**
	 * Constructs the test.
	 * 
	 * @param name
	 *            the name.
	 * @param phase
	 *            the phase.
	 * @param period
	 *            the period.
	 * @param executionTime
	 *            the maximum execution time.
	 * @param relativeDeadline
	 *            the relative deadline.
	 * @param processorNames
	 *            the processor names.
	 */
	public CreateTask(String name, long phase, long period, long executionTime,
			long relativeDeadline, String[] processorNames) {
		this.name = name;
		this.phase = phase;
		this.period = period;
		this.executionTime = executionTime;
		this.relativeDeadline = relativeDeadline;
		this.processorNames = new HashSet<>(Arrays.asList(processorNames));
	}

	/**
	 * Creates a {@link Task} to be used in the test.
	 * 
	 * @see Before
	 */
	@Before
	public void createTask() {
		task = new Task();
	}

	/**
	 * Tests the successful setting of the name.
	 */
	@Test
	public void testNameProperty() {
		task.setName(name);
		assertEquals(name, task.getName());
	}

	/**
	 * Tests the successful setting of the phase.
	 */
	@Test
	public void testPhaseProperty() {
		task.setPhase(phase);
		assertEquals(phase, task.getPhase());
	}

	/**
	 * Tests the successful setting of the period.
	 */
	@Test
	public void testPeriodProperty() {
		task.setPeriod(period);
		assertEquals(period, task.getPeriod());
	}

	/**
	 * Tests the successful setting of the maximum execution time.
	 */
	@Test
	public void testExecutionTimeProperty() {
		task.setExecutionTime(executionTime);
		assertEquals(executionTime, task.getExecutionTime());
	}

	/**
	 * Tests the successful setting of the relative deadline.
	 */
	@Test
	public void testRelativeDeadlineProperty() {
		task.setRelativeDeadline(relativeDeadline);
		assertEquals(relativeDeadline, task.getRelativeDeadline());
	}

	/**
	 * Tests the successful setting of the processor names.
	 */
	@Test
	public void testProcessorNamesProperty() {
		task.setProcessorNames(processorNames);
		assertEquals(processorNames, task.getProcessorNames());
		assertNotSame(processorNames, task.getProcessorNames());
	}
}
